package me.yokeyword.fragmentation.helper.internal;

import me.yokeyword.fragmentation.ISupportFraction;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.content.Intent;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.utils.PacMap;

public class VisibleDelegate {
    private static final String FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE = "fragmentation_invisible_when_leave";
    private static final String FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE = "fragmentation_compat_replace";

    // SupportVisible相关
    private boolean mIsSupportVisible;
    private boolean mInvisibleWhenLeave;
    private boolean mIsFirstVisible = true;
    private boolean mFirstCreateViewCompatReplace = true;
    private boolean mAbortInitVisible = false;
    private Runnable taskDispatchSupportVisible;

    private EventHandler mHandler;
    private Intent mSaveInstanceState;

    private ISupportFraction mSupportF;
    private Fraction mFraction;

    public VisibleDelegate(ISupportFraction fraction) {
        this.mSupportF = fraction;
        this.mFraction = (Fraction) fraction;
    }

    public void onCreate(Intent savedInstanceState) {
        if (savedInstanceState != null) {
            mSaveInstanceState = savedInstanceState;
            mInvisibleWhenLeave = savedInstanceState.getBooleanParam(FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE, false);
            mFirstCreateViewCompatReplace = savedInstanceState.getBooleanParam(FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE, false);
        }
    }

    public void onSaveInstanceState(PacMap outState) {
        outState.putBooleanValue(FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE, mInvisibleWhenLeave);
        outState.putBooleanValue(FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE, mFirstCreateViewCompatReplace);
    }

    public void onAbilityCreated(PacMap savedInstanceState) {
        if (!mFirstCreateViewCompatReplace/* && mFraction.getTag() != null*/) {
            return;
        }

        if (mFirstCreateViewCompatReplace) {
            mFirstCreateViewCompatReplace = false;
        }

        initVisible();
    }

    private void initVisible() {
    }

    public void onActive() {
        if (mIsFirstVisible) {
            if (mAbortInitVisible) {
                mAbortInitVisible = false;
                initVisible();
            }
        }
    }

    public void onInactive() {
        if (taskDispatchSupportVisible != null) {
            getHandler().removeTask(taskDispatchSupportVisible);
            mAbortInitVisible = true;
            return;
        }
        if (mIsSupportVisible && isFragmentVisible(mFraction)) {
            mInvisibleWhenLeave = false;
        } else {
            mInvisibleWhenLeave = true;
        }
    }

    public void onHiddenChanged(boolean hidden) {
        if (!hidden/* && !mFraction.isResumed()*/) {
            //if fraction is shown but not resumed, ignore...
            onFragmentShownWhenNotResumed();
            return;
        }
        if (hidden) {
            safeDispatchUserVisibleHint(false);
        } else {
            enqueueDispatchVisible();
        }
    }

    private void onFragmentShownWhenNotResumed() {
        mInvisibleWhenLeave = false;
    }

    public void onDestroyView() {
        mIsFirstVisible = true;
    }

    public void setUserVisibleHint(boolean isVisibleToUser) {
        if (!mIsSupportVisible && isVisibleToUser) {
            safeDispatchUserVisibleHint(true);
        }
    }

    private void safeDispatchUserVisibleHint(boolean visible) {
        if (mIsFirstVisible) {
            if (!visible) return;
            enqueueDispatchVisible();
        }
    }

    private void enqueueDispatchVisible() {
        taskDispatchSupportVisible = () -> {
            taskDispatchSupportVisible = null;
        };
        getHandler().postTask(taskDispatchSupportVisible);
    }

    private boolean isFragmentVisible(Fraction fraction) {
        return true;
    }

    public boolean isSupportVisible() {
        return mIsSupportVisible;
    }

    private EventHandler getHandler() {
        if (mHandler == null) {
            mHandler = new EventHandler(EventRunner.getMainEventRunner());
        }
        return mHandler;
    }
}
